//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================
#if _MSC_VER > 1000
#pragma once
#endif

#ifndef __IPCCHANNEL_H__
#define __IPCCHANNEL_H__

#include <elasys_server.h>
#include <linknode.h>
#include <aura.h>

#define INVALID_CHANNEL_ID ((Aura_ChannelId)-1)
#define DEFAULT_CHANNNELPOOL_CAPACITY (3)


typedef ECode (*InvokeFuncPTR)(Aura_ChannelId, PVoid, ECode*);

class CChannel: public DLinkNode
{
public:
    ECode Write(
        /* [in] */ PVoid pBuffer,
        /* [in] */ UInt32 bufferSize);

    ECode Read(
        /* [out] */ PVoid pBuffer,
        /* [in] */ UInt32 buffSize);

    ECode WriteAndRead(
        /* [in] */ PVoid pInBuffer,
        /* [in] */ UInt32 inBufferSize,
        /* [out] */ PVoid pOutBuffer,
        /* [in] */ UInt32 outBufferSize);

    ECode Invoke(
        /* [in] */ InvokeFuncPTR invokeFunc,
        /* [in] */ PVoid pArgs,
        /* [out] */ ECode * pResult);

public:
    CChannel(): m_channelId(INVALID_CHANNEL_ID){ DLinkNode::Initialize(); }
    ~CChannel();
    ECode Initialize(WString name);

private:
    Aura_ChannelId m_channelId;
};

class CChannelPool
{
public:
    ECode Write(
        /* [in] */ PVoid pBuffer,
        /* [in] */ UInt32 bufferSize);

    ECode Read(
        /* [out] */ PVoid pBuffer,
        /* [in] */ UInt32 bufferSize);

    ECode WriteAndRead(
        /* [in] */ PVoid pInBuffer,
        /* [in] */ UInt32 inBufferSize,
        /* [out] */ PVoid pOutBuffer,
        /* [in] */ UInt32 outBufferSize);

    ECode Invoke(
        /* [in] */ InvokeFuncPTR invokeFunc,
        /* [in] */ PVoid pArgs,
        /* [out] */ ECode * pResult);

public:
    CChannelPool(Int32 capactity = DEFAULT_CHANNNELPOOL_CAPACITY)
            : m_pName(NULL),
              m_capacity(capactity),
              m_hLock(NULL),
              m_channels(0) { m_channelList.Initialize(); }

    ~CChannelPool();

    ECode Initialize(WString name);

private:
    ECode GetChannel(
        /* [out] */ CChannel ** ppChannel);

    void PutbackChannel(
        /* [in] */ CChannel * pChannel);

    ECode CreateChannel(
        /* [out] */ CChannel ** ppChannel);

    void  DestroyChannel(
        /* [in] */ CChannel * pChannel);

    void  DestroyAllChannels();

private:
    WStringBuf * m_pName;
    Int32        m_capacity;

    DLinkNode m_channelList;
    PVoid     m_hLock;
    Int32     m_channels;
};

#endif // __IPCCHANNEL_H__

